home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 4 / Apprentice-Release4.iso / Source Code / C / Applications / Portable Patmos / src / portable kernel / mac / mmu.c copy < prev    next >
Encoding:
Text File  |  1994-12-18  |  44.2 KB  |  1,752 lines  |  [TEXT/KAHL]

  1. ed char ccnt;
  2.  
  3. void    *logical_to_physical(struct mmu *crp, unsigned long addr)
  4.     {
  5.     long    level1 = crp->level1[addr>>25]&~255;
  6. //    CHECK(addr);
  7.     if
  8.         (
  9.          (level1 >= (long)(crp->level2)
  10.          ) 
  11.         && 
  12.          (level1 < sizeof(crp->level2)+(long)(crp->level2)
  13.          )
  14.         )
  15.         {
  16.         long    level2 = ((long *)level1)[(addr>>18)&127]&~255;
  17.         if ((level2 >= (long)(crp->level3)) 
  18.             && (level2 < sizeof(crp->level3)+(long)(crp->level3)))
  19.             {
  20.             long    level3 = ((long *)level2)[(addr&((1<<18)-1))/page_size]&~255;
  21.             if (level3)
  22.                 return (void *)(level3+(addr&(page_size-1)));
  23.             }
  24.         }
  25.     return((void *)-1);
  26.     }
  27.  
  28. #define LTP(x)    logical_to_physical(crp, x)
  29. #define CHECK2(crp, addr)    if (check2(crp, addr)) return -1
  30.  
  31. int check2(struct mmu *crp, unsigned long addr)
  32.     {
  33.     Zone    *pzone = ApplicZone();
  34.     long    phys_addr = (long)LTP(addr);
  35.     if (phys_addr==-1)
  36.         {
  37.         crp->result = -1;
  38.         errno = EFAULT;
  39.         return -1;
  40.         }
  41.     if (debug && (addr >= crp->sbreak) 
  42.               && ((addr < crp->registers.save[15]) || (addr >= stack_limit)))
  43.                       {
  44.                     char err[99];
  45.                     ksprintf(err+1, "Possible bus error soon, logical address %8.8X\n", addr);
  46.                     *err = strlen(err+1);
  47.                       DebugStr(err);
  48.                       }
  49.     if ((phys_addr < (long)&(pzone->heapData)) || (phys_addr >= (long)(pzone->bkLim)))
  50.         {
  51.         char err[99];
  52.         ksprintf(err+1, "Physical address %8.8X outside kernel memory\n", phys_addr);
  53.         *err = strlen(err+1);
  54.         DebugStr(err);
  55.         }
  56.     return 0;
  57.     }
  58.  
  59. #define CHECK(addr) CHECK2(crp, addr)
  60.  
  61. void kprintf(char *, ...);
  62. int newproc(char *name, int exec, char **argv, char **envp);
  63. int ukmemcpy(struct mmu *crp, long dest, void *src, long siz);
  64. int kumemcpy(struct mmu *crp, void *dest, long src, long siz);
  65. long ustrlen(struct mmu *crp, long src);
  66. int kustrcpy(struct mmu *crp, void *dest, long src);
  67. int umemset(struct mmu *crp, long dest, char value, long siz);
  68. int upper_space(struct mmu *crp, long size);
  69. int lower_space(struct mmu *crp, long size);
  70. void free_space(struct mmu *crp);
  71. void *xmalloc(size_t siz);
  72. char *callname(int sel);
  73. void system_call(void);
  74.  
  75. void setmaxstack(long value)
  76.     {
  77.     crp->maxstack = value;
  78.     if (value > stack_headroom*2) value = stack_headroom*2;
  79.     upper_space(crp, value);
  80.     }
  81.  
  82. void sched(void)
  83.     {
  84.     static proc_no = 0;
  85.     static long sched_time = 0;
  86.     long now = get_ticks();
  87.     int cnt = sizeof(proc_tab)/sizeof(*proc_tab);
  88.     while (cnt--)
  89.         {
  90.         if (proc_tab[cnt] && (proc_tab[cnt]->state == 'Z'))
  91.             {
  92.             int arg = OPEN_MAX;
  93.             while (arg--) if (proc_tab[cnt]->fd_tab[arg])
  94.                 {
  95.                 int stale = 1;
  96.                 int kfd = proc_tab[cnt]->fd_tab[arg];
  97.                 int cnt1 = sizeof(proc_tab)/sizeof(*proc_tab);
  98.                 proc_tab[cnt]->fd_tab[arg] = 0;
  99.                 while (cnt1--)
  100.                     {
  101.                     if (proc_tab[cnt1] && (proc_tab[cnt1]->state != 'Z'))
  102.                         {
  103.                         int cnt2 = OPEN_MAX;
  104.                         while (cnt2--)
  105.                             {
  106.                             if (proc_tab[cnt1]->fd_tab[cnt2] == kfd)
  107.                                 {
  108. //                                kprintf("fd %d still open in proc %d\n", arg, proc_tab[cnt1]->pid);
  109.                                 stale = cnt1 = cnt2 = 0;
  110.                                 }
  111.                             }
  112.                         }
  113.                     }
  114.                 if (stale) close(kfd);
  115.                 }
  116.             free_space(proc_tab[cnt]);
  117.             if (debug)
  118.                 kprintf("Activated pages = %ld\n", activated_pages);
  119.             free(proc_tab[cnt]->self);
  120. //            mstats("MMU");
  121.             proc_tab[cnt] = 0;
  122.             }
  123.         }
  124.     if (crp->state != 'K')
  125.         {
  126.         crp->ticks += now-old_ticks;            
  127.         crp->state = 'D';
  128.         }
  129.     old_ticks = now;
  130.     do
  131.         {
  132.         if (crp->state != 'K')
  133.             {
  134.             cnt = -1;    
  135.             do
  136.                 {
  137.                 ++cnt;
  138.                 proc_no = (proc_no+1)%(sizeof(proc_tab)/sizeof(*proc_tab));
  139.                 }
  140.             while (
  141.                    (cnt <= sizeof(proc_tab)/sizeof(*proc_tab)
  142.                    ) 
  143.                   && 
  144.                    (!proc_tab[proc_no] 
  145.                     || (proc_tab[proc_no]->state != 'D')
  146.                    )
  147.                   );
  148.             if (cnt > sizeof(proc_tab)/sizeof(*proc_tab))
  149.                 {
  150.                 kInterval = 0;
  151.                 exit(2);
  152.                 }
  153.             crp = proc_tab[proc_no];
  154.             }
  155.         mysleep(1);
  156.         system_call();
  157.         mysleep(1);
  158.         cnt = 0;    
  159.         while (
  160.                (cnt < sizeof(proc_tab)/sizeof(*proc_tab)
  161.                ) 
  162.               && 
  163.                (!proc_tab[proc_no] 
  164.                 || (proc_tab[proc_no]->state != 'R')
  165.                )
  166.               )
  167.             {
  168.             ++cnt;
  169.             proc_no = (proc_no+1)%(sizeof(proc_tab)/sizeof(*proc_tab));
  170.             }
  171.         }
  172.     while (cnt >= sizeof(proc_tab)/sizeof(*proc_tab));
  173.     now = get_ticks();
  174.     sched_time += now-old_ticks;
  175.     old_ticks = now;
  176.     crp = proc_tab[proc_no];
  177.     }
  178.  
  179. struct args
  180.          {
  181.          void *dummy;
  182.          long arg1,arg2,arg3,arg4,arg5,arg6;
  183.          };
  184.  
  185. void system_call(void)
  186.     {
  187.      struct args s;
  188.      if (crp->state != 'K') crp->state = 'R'; /* runnable unless otherwise overridden */
  189.      kumemcpy(crp, &s, crp->registers.save[15], sizeof(s));
  190.     crt_parID = crp->crt_parID;
  191.     root_parID = crp->root_parID;
  192.      if (debug) 
  193.          {
  194.          kprintf("System call %s(%X,%X,%X)\n", callname(crp->registers.save[0]), s.arg1, s.arg2, s.arg3);
  195.          }
  196.     switch(crp->registers.save[0])
  197.         {
  198.         default: if (crp->state != 'K')
  199.             {
  200.             kprintf("Unimplemented system call %s\n", 
  201.                 callname(crp->registers.save[0]));
  202.             }
  203.         else
  204.             {
  205.              crp->state = 'R';    /* runnable unless otherwise overridden */
  206.              break;
  207.              }
  208.         case SYS_exit:
  209.             if (crp->parent && (crp->parent->state=='W'))
  210.                 {
  211.                 /* save parent->result of system call */
  212.                     {
  213.                     enum {carry=1};
  214.                         {
  215.                         if (crp->parent->result)
  216.                             {
  217.                             int waitcode = (s.arg1&255)<<8;
  218.                             ukmemcpy(crp->parent, crp->parent->result, &waitcode, sizeof(int)); /* for retcode */
  219.                             }
  220.                         crp->parent->registers.save[0] = crp->pid;
  221.                         crp->parent->registers.flags &= ~carry;
  222.                         }
  223.                     crp->parent->registers.save[1] = 0;    /* is this correct ? */
  224.                     }
  225.                 crp->parent->state = 'R';
  226.                 }
  227.             crp->state = 'Z';
  228.             break;
  229.         case SYS_fork:
  230.         case SYS_vfork:
  231.             newproc(0, 0, NULL, NULL);
  232.             crp->result = 0;
  233.             /* save parent->result of system call */
  234.                 {
  235.                 enum {carry=1};
  236.                     {
  237.                     crp->parent->registers.save[0] = crp->pid;
  238.                     crp->parent->registers.flags &= ~carry;
  239.                     }
  240.                 crp->parent->registers.save[1] = 0;    /* is this correct ? */
  241.                 }
  242.             break;
  243.         case SYS_read:
  244.             {
  245.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  246.             else
  247.                 {
  248.                 char *kbuf = xmalloc(s.arg3);
  249.                 int kfd = crp->fd_tab[s.arg1];
  250.                 crp->result = read(kfd, kbuf, s.arg3);
  251.                 ukmemcpy(crp, s.arg2, kbuf, crp->result);
  252.                 free(kbuf);
  253.                 if ((crt_fd_tab[kfd].flags & O_PIPE) && !crp->result)
  254.                     {
  255.                     int tot = 0;
  256.                     int cnt = sizeof(proc_tab)/sizeof(*proc_tab);
  257.                     while (cnt--)
  258.                         {
  259.                         if (proc_tab[cnt] && (proc_tab[cnt]->state != 'Z'))
  260.                             {
  261.                             int cnt2 = OPEN_MAX;
  262.                             while (cnt2--)
  263.                                 {
  264.                                 if (proc_tab[cnt]->fd_tab[cnt2] == kfd)
  265.                                     {
  266.                                     ++tot;
  267.                                     }
  268.                                 }
  269.                             }
  270.                         }
  271.                     if (tot > 1) crp->state = 'D';
  272.                     }
  273.                 }
  274.             break;
  275.             }
  276.         case SYS_write:
  277.             {
  278.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  279.             else
  280.                 {
  281.                 char *kbuf = xmalloc(s.arg3);
  282.                 kumemcpy(crp, kbuf, s.arg2, s.arg3);
  283.                 crp->result = write(crp->fd_tab[s.arg1], kbuf, s.arg3);
  284.                 free(kbuf);
  285.                 }
  286.             break;
  287.             }
  288.         case SYS_open:
  289.             {
  290.             int bufsiz = ustrlen(crp, s.arg1)+1;
  291.             char *kbuf = xmalloc(bufsiz);
  292.             kustrcpy(crp, (void *)kbuf, s.arg1);
  293.             if (debug) kprintf("Open %s\n", kbuf);    
  294.             crp->result = open(kbuf, s.arg2, s.arg3);
  295.             if (crp->result != -1)
  296.                 {
  297.                 int fd = 0;
  298.                 while ((fd <= OPEN_MAX) && crp->fd_tab[fd]) ++fd;
  299.                 if (fd <= OPEN_MAX) 
  300.                     {
  301.                     crp->fd_tab[fd] = crp->result;
  302.                     crp->result = fd;
  303.                     }
  304.                 else
  305.                     {
  306.                     close(crp->result);
  307.                     crp->result = -1;
  308.                     }
  309.                 }    
  310.             free((void *)kbuf);
  311.             break;
  312.             }
  313.         case SYS_close:
  314.             crp->result = -1;
  315.             if ((s.arg1>=0)&&(s.arg1<=OPEN_MAX)&&crp->fd_tab[s.arg1])
  316.                 {
  317.                 int kfd = crp->fd_tab[s.arg1];
  318.                 int cnt = sizeof(proc_tab)/sizeof(*proc_tab);
  319.                 crp->fd_tab[s.arg1] = 0;
  320.                 while (cnt--)
  321.                     {
  322.                     if (proc_tab[cnt] && (proc_tab[cnt]->state != 'Z'))
  323.                         {
  324.                         int cnt2 = OPEN_MAX;
  325.                         while (cnt2--)
  326.                             {
  327.                             if (proc_tab[cnt]->fd_tab[cnt2] == kfd)
  328.                                 {
  329. //                                kprintf("fd %d still open in proc %d\n", s.arg1, proc_tab[cnt]->pid);
  330.                                 crp->result = cnt = cnt2 = 0;
  331.                                 }
  332.                             }
  333.                         }
  334.                     }
  335.                 if (crp->result) crp->result = close(kfd);    
  336.                 }
  337.             break;
  338.         case SYS_wait4:
  339.             {
  340.             int proc_no = 0;
  341.             int cnt = sizeof(proc_tab)/sizeof(*proc_tab);
  342.             while (--cnt && (!proc_tab[proc_no] || (proc_tab[proc_no]->parent != crp) 
  343.                 || ((s.arg1 != -1) && (s.arg1 != proc_tab[proc_no]->pid))))
  344.                 ++proc_no;
  345.             if (cnt)
  346.                 {
  347.                 crp->result = s.arg2;
  348.                 crp->state = 'W';
  349.                 }
  350.             else    
  351.                 {
  352.                 errno = ECHILD;
  353.                 umemset(crp, s.arg2, 0, sizeof(int));
  354.                 crp->result = -1;
  355.                 }
  356.             break;
  357.             }
  358.         case SYS_link:
  359.             crp->result = -1;
  360.             break;
  361.         case SYS_unlink:
  362.             {
  363.             int bufsiz = ustrlen(crp, s.arg1)+1;
  364.             char *kbuf = xmalloc(bufsiz);
  365.             kustrcpy(crp, kbuf, s.arg1);            
  366.             crp->result = unlink(kbuf);
  367.             free(kbuf);
  368.             break;
  369.             }
  370.         case SYS_chdir:
  371.             {
  372.             int bufsiz = ustrlen(crp, s.arg1)+1;
  373.             char *kbuf = xmalloc(bufsiz);
  374.             kustrcpy(crp, kbuf, s.arg1);            
  375.             crp->result = chdir(kbuf);
  376.             if (!crp->result) crp->crt_parID = crt_parID;
  377.             free(kbuf);
  378.             break;
  379.             }
  380.         case SYS_fchdir:
  381.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  382.             else crp->result = fchdir(crp->fd_tab[s.arg1]);
  383.             if (!crp->result) crp->crt_parID = crt_parID;
  384.             break;
  385.         case SYS_chmod:
  386.             {
  387.             int bufsiz = ustrlen(crp, s.arg1)+1;
  388.             char *kbuf = xmalloc(bufsiz);
  389.             kustrcpy(crp, kbuf, s.arg1);            
  390.             crp->result = chmod(kbuf, s.arg2);
  391.             free(kbuf);
  392.             break;
  393.             }
  394.         case SYS_chown:
  395.             {
  396.             int bufsiz = ustrlen(crp, s.arg1)+1;
  397.             char *kbuf = xmalloc(bufsiz);
  398.             kustrcpy(crp, kbuf, s.arg1);            
  399.             crp->result = chown(kbuf, s.arg2, s.arg3);
  400.             free(kbuf);
  401.             break;
  402.             }
  403.         case SYS_lseek:
  404.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  405.             else crp->result = lseek(crp->fd_tab[s.arg1], s.arg2, s.arg3);
  406.             break;
  407.         case SYS_getpid:
  408.             crp->result = crp->pid;
  409.             break;
  410.         case SYS_getuid:
  411.             crp->result = 0;
  412.             break;
  413.         case SYS_geteuid:
  414.             crp->result = 0;
  415.             break;
  416.         case SYS_ptrace:
  417.             {
  418.             struct mmu *child = NULL;
  419.             int pid = s.arg2;
  420.             long addr = s.arg3;
  421.             long data = s.arg4;
  422.             int proc_no = 0;
  423.             int cnt = sizeof(proc_tab)/sizeof(*proc_tab);
  424.             while (--cnt && (!proc_tab[proc_no] || (pid != proc_tab[proc_no]->pid)))
  425.                 ++proc_no;
  426.             if (cnt)
  427.                 {
  428.                 child = proc_tab[proc_no];
  429.                 if ((child->state != 'T') || !child->trace_me)
  430.                     {
  431.                     errno = ECHILD;
  432.                     break;
  433.                     }
  434.                 else crp->result = 0;
  435.                 }
  436.             else    
  437.                 errno = ECHILD;
  438.             if (debug) kprintf("ptrace(%d,%d,%08X,%08X)\n", s.arg1, pid, addr, data);
  439.             switch(s.arg1)
  440.                 {
  441.                 case     PT_TRACE_ME    : if (debug) kprintf("child declares it's being traced\n");
  442.                     crp->trace_me = 1; 
  443.                     crp->result = 0;
  444.                     break;
  445.                 case     PT_READ_I    :
  446.                 case     PT_READ_D    : if (debug) kprintf("read word in child's I/D space\n"); 
  447.                     if (child)
  448.                         kumemcpy(child, &(crp->result), addr, sizeof(long));                    
  449.                     break;
  450.                 case     PT_READ_U    : kprintf("read word in child's user structure\n"); 
  451.                     crp->result = -1;
  452.                     break;
  453.                 case     PT_WRITE_I    :
  454.                 case     PT_WRITE_D    : if (debug) kprintf("write word in child's I/D space\n"); 
  455.                     if (child)
  456.                         ukmemcpy(child, addr, &data, sizeof(long));
  457.                     break;
  458.                 case     PT_WRITE_U    : kprintf("write word in child's user structure\n"); 
  459.                     crp->result = -1;
  460.                     break;
  461.                 case     PT_CONTINUE    : if (debug) kprintf("continue the child\n"); 
  462.                     {
  463.                     if (child) 
  464.                         child->state = 'R';
  465.                     break;
  466.                     }
  467.                 case     PT_KILL        : if (debug) kprintf("kill the child process\n"); 
  468.                     if (child) 
  469.                         child->state = 'Z';
  470.                     break;
  471.                 case     PT_STEP        : if (debug) kprintf("single step the child\n"); 
  472.                     if (child)
  473.                         {
  474.                         child->registers.flags |= 0x8000;
  475.                         child->state = 'R';
  476.                         }
  477.                     break;
  478.                 case     PT_ATTACH    : kprintf("attach to running process\n"); 
  479.                     crp->result = -1;
  480.                     break;
  481.                 case     PT_DETACH    : kprintf("detach from running process\n");
  482.                     crp->result = -1;
  483.                     break;
  484.                 case     PT_GETREGS    : if (debug) kprintf("fetch registers\n");
  485.                     if (child)
  486.                         ukmemcpy(crp, addr, &(child->registers), sizeof(struct userregs));
  487.                     break;
  488.                 case     PT_SETREGS    : if (debug) kprintf("set registers\n"); 
  489.                     if (child)
  490.                         kumemcpy(crp, &(child->registers), addr, sizeof(struct userregs));
  491.                     break;
  492.                 default : crp->result = -1;
  493.                 }
  494.             break;
  495.             }
  496.         case SYS_execve:
  497.             {
  498.             int proc;
  499.             int bufsiz = ustrlen(crp, s.arg1)+1;
  500.             struct mmu *parent = crp->parent;
  501.             char *kbuf = xmalloc(bufsiz);
  502.             kustrcpy(crp, kbuf, s.arg1);            
  503.             crp->result = newproc(kbuf, 1, (char **)s.arg2, (char **)s.arg3);
  504.             crp->parent = parent;
  505.             free(kbuf);
  506. #if 0
  507.             if (debug)
  508.                 {
  509.                 char debugstr[99];
  510.                 long phys_pc = (long)LTP(crp->registers.pc);
  511.                 ksprintf(debugstr+1, "PC kernel address = %8.8X\n", phys_pc);
  512.                 *debugstr = strlen(debugstr+1);
  513.                 kprintf(debugstr+1);
  514.                 DebugStr(debugstr);
  515.                 }
  516. #endif
  517.             if (crp->trace_me) crp->state = 'T';
  518.             else break;
  519.             if (crp->parent && (crp->parent->state=='W'))
  520.                 {
  521.                 /* save parent->result of system call */
  522.                     {
  523.                     enum {carry=1};
  524.                         {
  525.                         if (crp->parent->result)
  526.                             {
  527.                             int waitcode = W_STOPCODE(SIGTRAP);
  528.                             ukmemcpy(crp->parent, crp->parent->result, &waitcode, sizeof(int)); /* for retcode */
  529.                             }
  530.                         crp->parent->registers.save[0] = crp->pid;
  531.                         crp->parent->registers.flags &= ~carry;
  532.                         }
  533.                     crp->parent->registers.save[1] = 0;    /* is this correct ? */
  534.                     }
  535.                 crp->parent->state = 'R';
  536.                 }
  537.             break;
  538.             }
  539.         case SYS_umask:
  540.             crp->result = 0;
  541.             break;
  542.         case SYS_fstat:
  543.             {
  544.             struct stat kstat;
  545.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  546.             else crp->result = fstat(crp->fd_tab[s.arg1], &kstat);
  547.             ukmemcpy(crp, s.arg2, &kstat, sizeof(struct stat));
  548.             break;
  549.             }
  550.         case SYS_access:
  551.             {
  552.             int bufsiz = ustrlen(crp, s.arg1)+1;
  553.             char *kbuf = xmalloc(bufsiz);
  554.             kustrcpy(crp, kbuf, s.arg1);            
  555.             crp->result = access(kbuf, s.arg2);
  556.             free(kbuf);
  557.             break;
  558.             }
  559.         case SYS_kill:
  560.             crp->result = 0;
  561.             break;
  562.         case SYS_stat: case SYS_lstat:
  563.             {
  564.             int bufsiz = ustrlen(crp, s.arg1)+1;
  565.             struct stat kstat;
  566.             char *kbuf = xmalloc(bufsiz);
  567.             kustrcpy(crp, kbuf, s.arg1);            
  568.             crp->result = stat(kbuf, &kstat);
  569.             ukmemcpy(crp, s.arg2, &kstat, sizeof(struct stat));
  570.             free(kbuf);
  571.             break;
  572.             }
  573.         case SYS_getppid:
  574.             crp->result = 1;
  575.             break;
  576.         case SYS_dup:
  577.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  578.             else
  579.                 {
  580.                 int fd = 0;
  581.                 while ((fd <= OPEN_MAX) && crp->fd_tab[fd]) ++fd;
  582.                 if (fd <= OPEN_MAX) 
  583.                     {
  584.                     crp->fd_tab[fd] = s.arg1;
  585.                     crp->result = fd;
  586.                     }
  587.                 else
  588.                     {
  589.                     crp->result = -1;
  590.                     }
  591.                 }    
  592.             break;
  593.         case SYS_pipe:
  594.             {
  595.             int arg[2],i;
  596.             crp->result = pipe(arg);
  597.             if (!crp->result) for (i= 0; i < 2; i++)
  598.                 {
  599.                 int fd = 0;
  600.                 while ((fd <= OPEN_MAX) && crp->fd_tab[fd]) ++fd;
  601.                 if (fd <= OPEN_MAX) 
  602.                     {
  603.                     crp->fd_tab[fd] = arg[1];
  604.                     arg[i] = fd;
  605.                     }
  606.                 else
  607.                     {
  608.                     crp->result = -1;
  609.                     }
  610.                 }    
  611.             ukmemcpy(crp, s.arg1, arg, sizeof(arg));
  612.             if (debug) kprintf("pipe(%x[]={%x,%x}) returned %d\n", s.arg1, arg[0], arg[1], crp->result);
  613.             break;
  614.             }
  615.         case SYS_getegid:
  616.             crp->result = 0;
  617.             break;
  618.         case SYS_sigaction:
  619.             {
  620.             struct sigaction tmp_sig;
  621.             kumemcpy(crp, &tmp_sig, s.arg2, sizeof(struct sigaction));
  622.             crp->result = sigaction(s.arg1, &tmp_sig, &tmp_sig);
  623.             ukmemcpy(crp, s.arg3, &tmp_sig, sizeof(struct sigaction));
  624.             break;
  625.             }
  626.         case SYS_getgid:
  627.             crp->result = 0;
  628.             break;
  629.         case SYS_sigprocmask:
  630.             crp->result = 0;
  631.             break;
  632.         case SYS_getlogin:
  633.             crp->result = 0;
  634.             break;
  635.         case SYS_setlogin:
  636.             crp->result = -1;
  637.             break;
  638.         case SYS_ioctl:
  639.             {
  640.             void *kbuf = xmalloc(IOCPARM_LEN(s.arg2));
  641.             kumemcpy(crp, kbuf, s.arg3, IOCPARM_LEN(s.arg2));
  642.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  643.             else crp->result = ioctl(crp->fd_tab[s.arg1], s.arg2, kbuf);
  644.             ukmemcpy(crp, s.arg3, kbuf, IOCPARM_LEN(s.arg2));
  645.             free(kbuf);
  646.             break;
  647.             }
  648.         case SYS_getpagesize:
  649.             crp->result = page_size;
  650.             break;
  651.         case SYS_sbrk:
  652.             s.arg1 += crp->sbreak;
  653.         case SYS_break:
  654.             if (s.arg1 > crp->registers.save[15]-8192) crp->result = -1;
  655.             else
  656.                 {
  657.                 if (s.arg1 > crp->sbreak)
  658.                     {
  659.                     long siz = s.arg1 - crp->sbreak;
  660.                     if (lower_space(crp, s.arg1))
  661.                         crp->result = -1;
  662.                     else 
  663.                         {
  664.                         crp->result = crp->sbreak;
  665.                         crp->sbreak = s.arg1;
  666.                         umemset(crp, crp->result, 0, siz);
  667.                         }
  668.                     }
  669.                 }
  670.             break;
  671.         case SYS_mmap:
  672.             crp->result = (long)mmap((caddr_t)s.arg1,s.arg2,s.arg3,s.arg4,s.arg5,s.arg6);
  673.             break;
  674.         case SYS_getgroups:
  675.             {
  676.             int *groups = xmalloc(s.arg1*sizeof(int));
  677.             crp->result = getgroups(s.arg1, groups);
  678.             ukmemcpy(crp, s.arg2, groups, s.arg1*sizeof(int));
  679.             free(groups);
  680.             break;
  681.             }
  682.         case SYS_getpgrp:
  683.             crp->result = 12345;
  684.             break;
  685.         case SYS_setpgid:
  686.             crp->result = 0;
  687.             break;
  688.         case SYS_getdtablesize:
  689.             crp->result = getdtablesize();
  690.             break;
  691.         case SYS_dup2:
  692.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  693.             else
  694.                 {
  695.                 crp->fd_tab[s.arg2] = crp->fd_tab[s.arg1];
  696.                 crp->result = 0;
  697.                 }
  698.             break;
  699.         case SYS_fcntl:
  700.             if (debug) kprintf("fcntl(%d,%d,%d)\n", s.arg1, s.arg2, s.arg3);
  701.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  702.             else switch(s.arg2)
  703.                  {
  704.                  case F_DUPFD :
  705.                     {
  706.                     int fd = s.arg3;
  707.                     while ((fd <= OPEN_MAX) && crp->fd_tab[fd]) ++fd;
  708.                     if (fd <= OPEN_MAX) 
  709.                         {
  710.                         crp->fd_tab[fd] = crp->fd_tab[s.arg1];
  711.                         crp->result = fd;
  712.                         }
  713.                     else
  714.                         {
  715.                         crp->result = -1;
  716.                         }
  717.                      break;
  718.                      }
  719.                  case F_SETFD : 
  720.                      if (debug) kprintf("Set fd flags\n"); 
  721.                      crp->result = 0; break;
  722.                 case F_GETFL : 
  723.                     if (debug) kprintf("Get file status flags\n"); 
  724.                     crp->result = O_RDWR; break; /* dummy */
  725.                 case F_SETFL : 
  726.                     if (debug) kprintf("Set file status flags\n"); 
  727.                     crp->result = 0; break;
  728.                  default: kprintf("Unsupported fcntl cmd %d\n", s.arg2);
  729.                  }
  730.             break;
  731.         case SYS_sigstack:
  732.             crp->result = 0;
  733.             break;
  734.         case SYS_sigsuspend:
  735.             crp->result = 0;
  736.             crp->state = 'W';
  737.             break;
  738.         case SYS_gettimeofday:
  739.             {
  740.             struct timeval ktime;
  741.             struct timezone kzone;
  742.             memset(&kzone, 0, sizeof(kzone));
  743.             ktime.tv_sec = unixTime(get_time());
  744.             ktime.tv_usec = (get_ticks()%60)*1000000/60;
  745.             if (s.arg1) ukmemcpy(crp, s.arg1, &ktime, sizeof(ktime));
  746.             if (s.arg2) ukmemcpy(crp, s.arg2, &kzone, sizeof(kzone));
  747.             crp->result = 0;
  748.             break;
  749.             }
  750.         case SYS_getrusage:
  751.             {
  752.             struct rusage kusage;
  753.             memset(&kusage, 0, sizeof(kusage));
  754.             crp->result = 0;
  755.             kusage.ru_utime.tv_usec = (crp->ticks%60)*1000000L/60;
  756.             kusage.ru_utime.tv_sec = crp->ticks/60;
  757.             ukmemcpy(crp, s.arg2, &kusage, sizeof(kusage));
  758.             break;
  759.             }
  760.         case SYS_writev:
  761.             {
  762.             int i;
  763.             struct iovec *iov = xmalloc(s.arg3*sizeof(struct iovec));
  764.             kumemcpy(crp, iov, s.arg2, s.arg3*sizeof(struct iovec));
  765.             crp->result = 0;
  766.             for (i = 0; i < s.arg3; i++)        
  767.                 {
  768.                 char *kbuf = xmalloc(iov[i].iov_len);
  769.                 kumemcpy(crp, kbuf, (long)iov[i].iov_base, iov[i].iov_len);
  770.                 if ((crp->result==-1)||(s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1])
  771.                     {
  772.                     i = s.arg3;
  773.                     crp->result = -1;
  774.                     }
  775.                 else crp->result = write(crp->fd_tab[s.arg1], kbuf, iov[i].iov_len);
  776.                 free(kbuf);
  777.                 }
  778.             free(iov);
  779.             break;
  780.             }
  781.         case SYS_rename:
  782.             {
  783.             int bufsiz1 = ustrlen(crp, s.arg1)+1;
  784.             char *kbuf1 = xmalloc(bufsiz1);
  785.             int bufsiz2 = ustrlen(crp, s.arg2)+1;
  786.             char *kbuf2 = xmalloc(bufsiz2);
  787.             kustrcpy(crp, kbuf1, s.arg1);            
  788.             kustrcpy(crp, kbuf2, s.arg2);            
  789.             crp->result = rename(kbuf1, kbuf2);
  790.             free(kbuf1);
  791.             free(kbuf2);
  792.             break;
  793.             }
  794.         case SYS_ftruncate:
  795.             {
  796.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  797.             else crp->result = ftruncate(crp->fd_tab[s.arg1], s.arg2);
  798.             break;
  799.             }
  800.         case SYS_mkdir:
  801.             {
  802.             int bufsiz = ustrlen(crp, s.arg1)+1;
  803.             char *kbuf = xmalloc(bufsiz);
  804.             kustrcpy(crp, kbuf, s.arg1);            
  805.             crp->result = mkdir(kbuf, s.arg2);
  806.             free(kbuf);        
  807.             break;
  808.             }
  809.         case SYS_rmdir:
  810.             {
  811.             int bufsiz = ustrlen(crp, s.arg1)+1;
  812.             char *kbuf = xmalloc(bufsiz);
  813.             kustrcpy(crp, kbuf, s.arg1);            
  814.             crp->result = rmdir(kbuf);    
  815.             free(kbuf);        
  816.             break;
  817.             }
  818.         case SYS_utimes:
  819.             {
  820.             struct timeval temps;
  821.             int bufsiz = ustrlen(crp, s.arg1)+1;
  822.             char *kbuf = xmalloc(bufsiz);
  823.             kustrcpy(crp, kbuf, s.arg1);            
  824.             kumemcpy(crp, &temps, s.arg2, sizeof(temps));
  825.             crp->result = utimes(kbuf, &temps);
  826.             break;
  827.             }
  828.         case SYS_getrlimit:
  829.             {
  830.             struct rlimit klimit;
  831.             crp->result = getrlimit(s.arg1, &klimit);
  832.             ukmemcpy(crp, s.arg2, &klimit, sizeof(struct rlimit));
  833.             break;
  834.             }
  835.         case SYS_setrlimit:
  836.             {
  837.             struct rlimit klimit;
  838.             kumemcpy(crp, &klimit, s.arg2, sizeof(struct rlimit));
  839.             crp->result = setrlimit(s.arg1, &klimit);
  840.             break;
  841.             }
  842.         case SYS_getdirentries:
  843.             {
  844.             long actualsize;
  845.             char *kbuf = xmalloc(s.arg3);
  846.             if ((s.arg1<0)||(s.arg1>OPEN_MAX)||!crp->fd_tab[s.arg1]) crp->result = -1;
  847.             else crp->result = getdirentries(crp->fd_tab[s.arg1], kbuf, s.arg3, &actualsize);
  848.             ukmemcpy(crp, s.arg2, kbuf, s.arg3);
  849.             ukmemcpy(crp, s.arg4, &actualsize, sizeof(long));
  850.             break;
  851.             }
  852.         }
  853.      if (debug && (crp->result==-1))
  854.          {
  855.          kprintf("Failed system call %s(%X,%X,%X)\n", callname(crp->registers.save[0]), s.arg1, s.arg2, s.arg3);
  856.          }
  857.     /* save crp->result of system call */
  858.     if (crp->state == 'R')
  859.         {
  860.         enum {carry=1};
  861.         if (crp->result==-1)
  862.             {
  863.             crp->registers.save[0] = errno;
  864.             crp->registers.flags |= carry;
  865.             }
  866.         else
  867.             {
  868.             crp->registers.save[0] = crp->result;
  869.             crp->registers.flags &= ~carry;
  870.             }
  871. //        crp->registers.save[1] = 0;    /* is this correct ? */
  872.         }
  873.     }
  874.  
  875. static pascal void trap_patch_0(void)
  876.      {
  877.     cpusha();
  878.     pflusha();
  879.     pflushan();
  880. //     Debugger();
  881.     /* save the current context */
  882.          {
  883.          struct userregs save;
  884.         asm { 
  885.             movem.l    d0-d7/a0-a5,save.save
  886.             move.l    (a6),save.save[14]
  887.             move.w    4(a6),save.flags
  888.             move.l    6(a6),save.pc
  889.             };
  890.         put_vbr(0);
  891.         SetCurrentA5();
  892.         save.save[15] = usp();
  893.         SetCursor(*nxt[7&++ccnt]);
  894.         if (0x2000&~save.flags)
  895.             {
  896.             crp->registers = save;
  897.             crp->state = 'W';
  898.             }
  899.         else crp->state = 'K';
  900.         }
  901. #if 0
  902.             kprintf("Saved PC = %X USP = %X URP = %X\n", 
  903.                 crp->registers.pc, 
  904.                 crp->registers.save[15], 
  905.                 (long)crp);
  906. #endif
  907.     sched();
  908. #if 0
  909.             kprintf("Restored PC = %X USP = %X URP = %X\n", 
  910.                 crp->registers.pc, 
  911.                 crp->registers.save[15], 
  912.                 (long)crp);
  913. #endif
  914.     /* restore the chosen context */
  915.          {
  916.          struct userregs save = crp->registers;
  917.          put_urp((long)crp);
  918.         put_usp(save.save[15]);
  919.         upper_space(crp, stack_limit-save.save[15]+stack_headroom);
  920.         cpusha();
  921.         pflusha();
  922.         pflushan();
  923.         put_vbr((long)user_vectors);
  924.         asm
  925.             {
  926.             move.l    save.save[14],(a6)
  927.             move.w    save.flags,4(a6)
  928.             move.l    save.pc,6(a6)
  929.             movem.l    save.save,d0-d7/a0-a5
  930.             unlk    a6
  931.              rte 
  932.              };
  933.         }
  934.      }
  935.  
  936. static pascal void trap_patch_1(unsigned short fault)
  937.      {
  938.      unsigned short    kind;
  939.      long newstacksize,phys_pc;
  940.     /* save the current context */
  941.      struct userregs save;
  942.     cpusha();
  943.     pflusha();
  944.     pflushan();
  945.     asm { 
  946.         movem.l    d0-d7/a0-a5,save.save
  947.         };
  948.     put_vbr(0);
  949.     SetCurrentA5();
  950.     SetCursor(*nxt[7&++ccnt]);
  951.     newstacksize = stack_limit-usp()+stack_headroom;
  952.     if ((newstacksize<stack_headroom) 
  953.         || newstacksize > crp->maxstack
  954.         || ((long)(LTP(usp()))!=-1) 
  955.         || upper_space(crp, newstacksize))
  956.             {
  957.             int i,k;
  958.             save.save[15] = usp();
  959.             asm { 
  960.                 move.l    (a6),save.save[14]
  961.                 move.w    4(a6),save.flags
  962.                 move.l    6(a6),save.pc
  963.                 move.w    10(a6),kind
  964.                 };
  965.             k = kind >> 12;
  966.             kind &= 4095;
  967.             if ((kind == (46<<2)) && (urp()==(long)swapper))
  968.                 {
  969.                 save.pc -= 2;
  970.                 crp->registers = save;
  971.                 }
  972.             else if (crp->trace_me && (0x2000&~save.flags) 
  973.                     && (((kind)==(9<<2))||((kind)==(47<<2))))
  974.                 {
  975.                 /* Breakpoint */
  976.                 save.flags &= ~0xC000;    /* disable tracing */
  977.                 crp->registers = save;
  978.                 crp->state = 'T';
  979.                 if (crp->parent && (crp->parent->state=='W'))
  980.                     {
  981.                     /* save parent->result of system call */
  982.                         {
  983.                         enum {carry=1};
  984.                             {
  985.                             if (crp->parent->result)
  986.                                 {
  987.                                 int waitcode = W_STOPCODE(SIGTRAP);
  988.                                 ukmemcpy(crp->parent, crp->parent->result, &waitcode, sizeof(int)); /* for retcode */
  989.                                 }
  990.                             crp->parent->registers.save[0] = crp->pid;
  991.                             crp->parent->registers.flags &= ~carry;
  992.                             }
  993.                         crp->parent->registers.save[1] = 0;    /* is this correct ? */
  994.                         }
  995.                     crp->parent->state = 'R';
  996.                     }
  997.                 crp = crp->parent;    
  998.                 }
  999.             else
  1000.                 {
  1001.                 kprintf("Saved PC = %X USP = %X URP = %X SR = %X\n", 
  1002.                     save.pc, 
  1003.                     save.save[15], 
  1004.                     (long)crp, save.flags);
  1005.                 kprintf("Exception vector = %X, kind = %d\n", 
  1006.                     kind, k);
  1007.                 for (i = 0; i < 8; i++)
  1008.                     kprintf("D%d = %8.8X    A%d = %8.8X\n", i, save.save[i], i, save.save[i+8]);
  1009.                 switch ((kind)>>2)
  1010.                     {
  1011.                     case 32: case 33: case 34: case 35:
  1012.                     case 36: case 37: case 38: case 39:
  1013.                     case 40: case 41: case 42: case 43:
  1014.                     case 44: case 45: case 46: case 47:
  1015.                         kprintf("trap #%d \n", ((kind)>>2)-32);
  1016.                         break;
  1017.                     case 2: kprintf("bus error - Fault frame:\n");
  1018.                         {
  1019.                         int i,addr;
  1020.                         unsigned short ssw,*fault_frame = &fault;
  1021.                         for (i = 4; i < 14; i++)
  1022.                             {
  1023.                             kprintf("%4.4X ", fault_frame[i]);
  1024.                             }
  1025.                         ssw = fault_frame[4];
  1026.                         addr = *(long *)&fault_frame[8];
  1027.                         kprintf("\nAccessing fault address %8.8X (kmem=%8.8X)\n", addr, LTP(addr));
  1028.                         break;
  1029.                         }
  1030.                     case 3: kprintf("address error\n"); break;
  1031.                     case 4: kprintf("illegal inst\n"); break;
  1032.                     case 5: kprintf("zeide\n"); break;
  1033.                     case 6: kprintf("range error\n"); break;
  1034.                     case 7: kprintf("trapv\n"); break;
  1035.                     case 8: kprintf("privilege\n"); break;
  1036.                     case 9: kprintf("trace\n"); break;
  1037.                     case 10: kprintf("line-A emulation\n"); break;
  1038.                     case 11: kprintf("Line-F emulation\n"); break;
  1039.                     }
  1040.                 phys_pc = (long)LTP(save.pc);
  1041.                 if (phys_pc != -1) insn_surround(save.pc);
  1042.                 else kprintf("Program address not mapped\n");
  1043.                 if (0x2000&~save.flags)
  1044.                     {
  1045.                      struct args s;
  1046.                      save.save[15] = stack_limit-sizeof(s);    /* in case stack bad */
  1047.                     crp->registers = save;
  1048.                     crp->registers.save[0] = SYS_exit;    /* exit on any exception */
  1049.                      memset(&s, 0, sizeof(s));
  1050.                      s.arg1 = 255;
  1051.                      ukmemcpy(crp, crp->registers.save[15], &s, sizeof(s));
  1052.                     }
  1053.                 else
  1054.                     {
  1055.                     kprintf("Exception occurred in supervisor mode\n");
  1056.                     kInterval = 0;
  1057.                     exit(1);
  1058.                     }
  1059.                 sched();
  1060.                 kprintf("Restored PC = %X USP = %X URP = %X\n", 
  1061.                     crp->registers.pc, 
  1062.                     crp->registers.save[15], 
  1063.                     (long)crp);
  1064.                 }
  1065.             /* restore the chosen context */
  1066.             save = crp->registers;
  1067.              put_urp((long)crp);
  1068.             put_usp(save.save[15]);
  1069.             cpusha();
  1070.             pflusha();
  1071.             pflushan();
  1072.             put_vbr((long)user_vectors);
  1073.             asm
  1074.                 {
  1075.                 move.l    save.save[14],(a6)
  1076.                 move.w    save.flags,4(a6)
  1077.                 move.l    save.pc,6(a6)
  1078.                 movem.l    save.save,d0-d7/a0-a5
  1079.                 unlk    a6
  1080.                  rte 
  1081.                  };
  1082.              }
  1083.     kprintf("New stack size = %d pages\n", newstacksize/page_size);
  1084.     put_vbr((long)user_vectors);
  1085.     asm
  1086.         {
  1087.         movem.l    save.save,d0-d7/a0-a5
  1088.         unlk    a6
  1089.          rte 
  1090.          };
  1091.     }
  1092.  
  1093. void patch_traps(void)
  1094.     {
  1095.     int i = 16;
  1096.     long *system_vectors = (long *)0x0;
  1097.     system_vectors[32] = (long)trap_patch_0;
  1098.     memcpy(user_vectors, 0, sizeof(user_vectors));
  1099.     while (--i) user_vectors[i+32] = (long)trap_patch_1;
  1100.     user_vectors[32] = (long)trap_patch_0;
  1101.     user_vectors[2] = (long)trap_patch_1;    /* bus error */
  1102.     user_vectors[3] = (long)trap_patch_1;    /* address error */
  1103.     user_vectors[4] = (long)trap_patch_1;    /* illegal inst */
  1104.     user_vectors[5] = (long)trap_patch_1;    /* zero divide */
  1105.     user_vectors[6] = (long)trap_patch_1;    /* range error */
  1106.     user_vectors[7] = (long)trap_patch_1;    /* trapv */
  1107.     user_vectors[8] = (long)trap_patch_1;    /* privilege */
  1108.     user_vectors[9] = (long)trap_patch_1;    /* trace */
  1109. //    user_vectors[10] = (long)trap_patch_1;    /* line-A emulation */
  1110.     user_vectors[11] = (long)trap_patch_1;    /* Line-F emulation */
  1111.     }
  1112.  
  1113. void *xmalloc(size_t siz)
  1114.     {
  1115.     static recursive = 0;
  1116.     void *ptr = malloc(siz);
  1117.     if (!ptr)
  1118.         {
  1119.         kInterval = 0;
  1120.         if (recursive) 
  1121.             {
  1122.             ExitToShell();
  1123.             }
  1124.         recursive = 1;
  1125.         kprintf("Out of memory\n");
  1126.         while (!Button());
  1127.         exit(1);
  1128.         }
  1129.     memset(ptr, 0, siz);
  1130.     return ptr;
  1131.     }
  1132.  
  1133. int ukmemcpy(struct mmu *crp, long dest, void *src, long siz)
  1134.     {
  1135.     if (siz > 0)
  1136.         {
  1137.         CHECK(dest);
  1138.         CHECK(dest+siz-1);
  1139.         put_urp((long)crp);
  1140.         pflusha();
  1141.         put_dfc(2);
  1142.         asm    {
  1143.             move.l    siz,d1
  1144.             move.l    src,a1
  1145.             move.l    dest,a0
  1146.         @1:    move.b    (a1)+,d0
  1147.             moves.b    d0,(a0)+
  1148.             subq.l    #1,d1
  1149.             bne        @1
  1150.             }
  1151.         }
  1152.     return 0;
  1153.     }
  1154.     
  1155. long ustrlen(struct mmu *crp, long src)
  1156.     {
  1157.     long result;
  1158.     CHECK(src);
  1159.     put_urp((long)crp);
  1160.     pflusha();
  1161.     put_sfc(2);
  1162.     asm    {
  1163.         move.l    src,a1
  1164.     @1:    moves.b    (a1)+,d0
  1165.         tst.b    d0
  1166.         bne        @1
  1167.         move.l    a1,result
  1168.         }
  1169.     return result-src-1;
  1170.     }
  1171.  
  1172. int kustrcpy(struct mmu *crp, void *dest, long src)
  1173.     {
  1174.     CHECK(src);
  1175.     put_urp((long)crp);
  1176.     pflusha();
  1177.     put_sfc(2);
  1178.     asm    {
  1179.         move.l    src,a1
  1180.         move.l    dest,a0
  1181.     @1:    moves.b    (a1)+,d0
  1182.         move.b    d0,(a0)+
  1183.         bne        @1
  1184.         }
  1185.     return 0;
  1186.     }
  1187.  
  1188. int kumemcpy(struct mmu *crp, void *dest, long src, long siz)
  1189.     {
  1190.     if (siz > 0)
  1191.         {
  1192.         CHECK(src);
  1193.         CHECK(src+siz-1);
  1194.         put_urp((long)crp);
  1195.         pflusha();
  1196.         put_sfc(2);
  1197.         asm    {
  1198.             move.l    siz,d1
  1199.             move.l    src,a1
  1200.             move.l    dest,a0
  1201.         @1:    moves.b    (a1)+,d0
  1202.             move.b    d0,(a0)+
  1203.             subq.l    #1,d1
  1204.             bne        @1
  1205.             }
  1206.         }
  1207.     return 0;
  1208.     }
  1209.  
  1210. void read_memory(long addr, void *buf, long maxlen)
  1211.     {
  1212.     kumemcpy(crp, buf, addr, maxlen);
  1213.     }
  1214.  
  1215. int umemset(struct mmu *crp, long dest, char value, long siz)
  1216.     {
  1217.     if (siz > 0)
  1218.         {
  1219.         CHECK(dest);
  1220.         CHECK(dest+siz-1);
  1221.         put_urp((long)crp);
  1222.         pflusha();
  1223.         put_dfc(2);
  1224.         asm    {
  1225.             move.l    siz,d1
  1226.             move.b    value,d0
  1227.             move.l    dest,a0
  1228.         @1:    moves.b    d0,(a0)+
  1229.             subq.l    #1,d1
  1230.             bne        @1
  1231.             }
  1232.         }
  1233.     return 0;
  1234.     }
  1235.  
  1236. int uumemcpy(struct mmu *destrp, struct mmu *srcrp, long dest, long src, long size)
  1237.     {
  1238.     enum     {bufsiz=8192};
  1239.     char    *kbuf = xmalloc(bufsiz);
  1240.     long    uaddr = 0;
  1241.     CHECK2(srcrp, src);
  1242.     CHECK2(destrp, dest);
  1243.     CHECK2(srcrp, src+size-1);
  1244.     CHECK2(destrp, dest+size-1);
  1245.     while (size > 0)
  1246.         {
  1247.         long amount = size>bufsiz?bufsiz:size;
  1248.         kumemcpy(srcrp, kbuf, src, amount);
  1249.         src += amount;
  1250.         ukmemcpy(destrp, dest, kbuf, amount);
  1251.         dest += amount;
  1252.         size -= amount;
  1253.         }
  1254.     free(kbuf);
  1255.     return 0;
  1256.     }
  1257.  
  1258. int uread(struct mmu *crp, int fd, long useraddr, long size)
  1259.     {
  1260.     enum    {bufsiz=8192};
  1261.     char    *kbuf = xmalloc(bufsiz);
  1262.     while (size > 0)
  1263.         {
  1264.         long amount = size>bufsiz?bufsiz:size;
  1265.         long actual = read(fd, kbuf, amount);
  1266.         if (actual > 0)
  1267.             {
  1268.             ukmemcpy(crp, useraddr, kbuf, actual);
  1269.             useraddr += actual;
  1270.             size -= actual;
  1271.             }
  1272.         else 
  1273.             {
  1274.             if (!actual) kprintf("Caution - executable too short for header\n");
  1275.             size = 0;
  1276.             }
  1277.         }
  1278.     free(kbuf);
  1279.     return 0;
  1280.     }
  1281.  
  1282. int page_free(long addr)
  1283.     {
  1284.     struct page_chain *ptr = head;
  1285.     long buf,tries;
  1286.     if (addr) while (ptr)
  1287.         {
  1288.         if (((ptr->free_list[0]&~0x80000000L) <= addr) && 
  1289.             ((ptr->free_list[sizeof(head->pages)/page_size-1]&~0x80000000L) >= addr))
  1290.             {
  1291.             buf = (addr - (ptr->free_list[0]&~0x80000000L))/page_size;
  1292.             if (ptr->free_list[buf] == ((addr&~(page_size-1))|0x80000000L))
  1293.                 {
  1294.                 ptr->free_list[buf] &= ~0x80000000L;
  1295.                 if (ptr->idx == -1) ptr->idx = buf;
  1296.                 return --activated_pages;
  1297.                 }
  1298.             }
  1299.         ptr = ptr->nxt;
  1300.         }
  1301.     return activated_pages;
  1302.     }
  1303.  
  1304. long page_alloc(void)
  1305.     {
  1306.     struct page_chain *ptr = head;
  1307.     long buf,tries;
  1308.     while (ptr)
  1309.         {
  1310.         tries = 256;
  1311.         if (ptr->idx != -1)
  1312.             {
  1313.             do
  1314.                 ptr->idx = (ptr->idx+1)&255;
  1315.             while ((ptr->free_list[ptr->idx] <= 0) && --tries);
  1316.             if (tries)
  1317.                 {
  1318.                 buf = ptr->free_list[ptr->idx];
  1319.                 ptr->free_list[ptr->idx] ^= 0x80000000L;
  1320.                 ++activated_pages;
  1321.                 memset((void *)buf, 0, page_size);
  1322.                 return buf;
  1323.                 }
  1324.             else ptr->idx = -1;    /* all pages used */
  1325.             }
  1326.         ptr = ptr->nxt;
  1327.         }
  1328.     ptr = malloc(sizeof(struct page_chain));
  1329.     if (ptr)
  1330.         {
  1331.         ptr->nxt = head;
  1332.         head = ptr;
  1333.         buf = ((((long)head->padding)|(page_size-1))+1);
  1334.         tries = sizeof(head->pages)/page_size;
  1335.         while (tries--)
  1336.             head->free_list[tries] = buf+tries*page_size;
  1337.         head->free_list[head->idx] ^= 0x80000000L;
  1338.         ++activated_pages;
  1339.         memset((void *)buf, 0, page_size);
  1340.         return buf;
  1341.         }
  1342.     errno = ENOMEM;
  1343.     return 0;
  1344.     }
  1345.  
  1346. int    upper_space(struct mmu *crp, long size)
  1347.     {
  1348.     long addr,level2;
  1349.     for (level2 = 128; level2--; )
  1350.         {
  1351.         for (addr = (1<<18)/page_size; addr--; )
  1352.             {
  1353.             if (!crp->level3[level2][addr])
  1354.                 {
  1355.                 long page = page_alloc();
  1356.                 if (page) crp->level3[level2][addr] = 0x39 + page;
  1357.                 else return -1;
  1358.                 }
  1359.             size -= page_size;
  1360.             if (size <= 0) return 0;
  1361.             }
  1362.         }
  1363.     return -1;
  1364.     }
  1365.  
  1366. int    lower_space(struct mmu *crp, long size)
  1367.     {
  1368.     long addr,level2;
  1369.     for (level2 = 0; level2 < 128; level2++)
  1370.         {
  1371.         for (addr = 0; addr < (1<<18)/page_size; addr++)
  1372.             {
  1373.             if (!crp->level3[level2][addr])
  1374.                 {
  1375.                 long page = page_alloc();
  1376.                 if (page) crp->level3[level2][addr] = 0x39 + page;
  1377.                 else return -1;
  1378.                 }
  1379.             size -= page_size;
  1380.             if (size <= 0) return 0;
  1381.             }
  1382.         }
  1383.     return -1;
  1384.     }
  1385.  
  1386. caddr_t mmap(caddr_t caddr, size_t size, int prot, int flags, int fd, off_t pos)
  1387.     {
  1388.     long level2;
  1389.     long laddr = (long)caddr;
  1390.     /*
  1391.      * Make sure one of the sharing types is specified
  1392.      */
  1393.     int mtype = flags & MAP_TYPE;
  1394.     errno = EINVAL;
  1395.     switch (mtype) {
  1396.     case MAP_FILE:
  1397.         if ((fd<0)||(fd>OPEN_MAX)||!crp->fd_tab[fd]) return((caddr_t)-1);
  1398.         if (lseek(crp->fd_tab[fd], pos, SEEK_SET) < 0)
  1399.             return((caddr_t)-1);
  1400.         kprintf("File ");
  1401.         break;
  1402.     case MAP_ANON:
  1403.         kprintf("Anon ");
  1404.         break;
  1405.     default:
  1406.         return((caddr_t)-1);
  1407.     }
  1408.     kprintf("mmap(%8X,%8X,%8X,%8X,%8X,%8X);\n", laddr, size, prot, flags, fd, pos);
  1409.     /*
  1410.      * Address (if FIXED) must be page aligned.
  1411.      * Size is implicitly rounded to a page boundary.
  1412.      */
  1413.     if ((flags & MAP_FIXED) && (laddr & (page_size-1)) || size < 0)
  1414.         {
  1415.         return((caddr_t)-1);
  1416.         }
  1417.  
  1418.     if (laddr == 0 && (flags & MAP_FIXED) == 0)
  1419.         {
  1420.         laddr = stack_limit>>2;
  1421.         }
  1422.  
  1423.     for (level2 = laddr/(1<<18); level2 < 128; level2++)
  1424.         {
  1425.         long addr;
  1426.         for (addr = (laddr&((1<<18)-1))/page_size; addr < (1<<18)/page_size; addr++)
  1427.             {
  1428.             if (!crp->level3[level2][addr])
  1429.                 {
  1430.                 long page = page_alloc();
  1431.                 if (page) crp->level3[level2][addr] = 0x39 + page;
  1432.                 else return ((caddr_t)-1);
  1433.                 }
  1434.             if (mtype == MAP_FILE)
  1435.                 {
  1436.                 char *kbuf = (char *)(crp->level3[level2][addr]&~(page_size-1));
  1437.                 long actual = read(crp->fd_tab[fd], kbuf, page_size);
  1438.                 if (actual < 0) return((caddr_t)-1);
  1439.                 }
  1440.             size -= page_size;
  1441.             if (((long)size) <= 0) 
  1442.                 {
  1443.                 return ((caddr_t)laddr);
  1444.                 }
  1445.             }
  1446.         }
  1447.         return((caddr_t)-1);
  1448.     }
  1449.  
  1450. void free_space(struct mmu *crp)
  1451.     {
  1452.     long addr,level2;
  1453.     cpusha();
  1454.     for (level2 = 0; level2 < 128; level2++)
  1455.         {
  1456.         for (addr = 0; addr < (1<<18)/page_size; addr++)
  1457.             {
  1458.             page_free(crp->level3[level2][addr]&~255);
  1459.             }
  1460.         }
  1461.     }
  1462.  
  1463. int newproc(char *kbuf, int exec_flag, char **argv, char **envp)
  1464.     {
  1465.     long addr2,addr,argcnt = 0,envcnt = 0;
  1466.     long siz = 0;
  1467.     static short nxt_pid = 0;
  1468.     struct mmu *parent = crp;
  1469.     char **args,**envs;
  1470.     if (exec_flag)
  1471.         {
  1472.         enum    {maxargs=2048,maxenv=2048};
  1473.         char **argp = argv;
  1474.         char **env = envp;
  1475.         char *ptr;
  1476.         args = (char **)xmalloc(maxargs*sizeof(char *));
  1477.         envs = (char **)xmalloc(maxenv*sizeof(char *));
  1478.         argcnt = 0;
  1479.         envcnt = 0;
  1480.         do
  1481.             {
  1482.             kumemcpy(parent, &ptr, (long)argp, sizeof(char *));
  1483.             if (ptr)
  1484.                 {
  1485.                 long bufsiz = ustrlen(parent, (long)ptr)+1;
  1486.                 char *kbuf = xmalloc(bufsiz);
  1487.                 kustrcpy(parent, kbuf, (long)ptr);
  1488.                 args[argcnt] = kbuf;
  1489.                 ++argcnt;
  1490.                 ++argp;
  1491.                 }
  1492.             }
  1493.         while (ptr && (argcnt<maxargs));
  1494.         do
  1495.             {
  1496.             kumemcpy(parent, &ptr, (long)env, sizeof(char *));
  1497.             if (ptr)
  1498.                 {
  1499.                 long bufsiz = ustrlen(parent, (long)ptr)+1;
  1500.                 char *kbuf = xmalloc(bufsiz);
  1501.                 kustrcpy(parent, kbuf, (long)ptr);
  1502.                 envs[envcnt] = kbuf;
  1503.                 ++envcnt;
  1504.                 ++env;
  1505.                 }
  1506.             }
  1507.         while (ptr && (envcnt<maxenv));
  1508.         }
  1509.     else ++nxt_pid;
  1510.         {
  1511.         int proc_no = 0;
  1512.         char *buf = (void *)xmalloc(512+sizeof(struct mmu));
  1513.         crp = (struct mmu *)((((long)buf)|511)+1);
  1514.         crp->self = buf;
  1515.         crp->parent = parent;
  1516.         crp->root_parID = root_parID;
  1517.         crp->crt_parID = crt_parID;
  1518.         crp->pid = nxt_pid;
  1519.         crp->state = 'R';
  1520.         while (proc_tab[proc_no] && (proc_no < sizeof(proc_tab)/sizeof(*proc_tab)))
  1521.             ++proc_no;
  1522.         if (proc_tab[proc_no])
  1523.             {
  1524.             kInterval = 0;
  1525.             exit(1);
  1526.             }
  1527.         proc_tab[proc_no] = crp;
  1528.         for (addr = 0; addr < 128; addr++)
  1529.             {
  1530.             crp->level1[addr] = 0x18;
  1531.             crp->level2[addr] = 0xA + (long)&(crp->level3[addr][0]);
  1532.             }
  1533.         crp->level1[0] = 0xA + (long)(crp->level2);
  1534.         if (upper_space(crp, stack_headroom))
  1535.             {
  1536.             crp->state = 'Z';
  1537.             return -1;
  1538.             }
  1539.         }
  1540.     if (exec_flag)
  1541.         {
  1542. #if 1
  1543.         long *addr = (long *)(stack_limit-256);
  1544.         long i;
  1545.         for (i = envcnt; i--; )
  1546.             {
  1547.             int len = strlen(envs[i]);
  1548.             addr -= len+4 >> 2;
  1549.             ukmemcpy(crp, (long)addr, envs[i], len+1);
  1550.             free(envs[i]);
  1551.             envs[i] = (char *)addr;
  1552.             }
  1553.         for (i = argcnt; i--; )
  1554.             {
  1555.             int len = strlen(args[i]);
  1556.             addr -= len+4 >> 2;
  1557.             ukmemcpy(crp, (long)addr, args[i], len+1);
  1558.             free(args[i]);
  1559.             args[i] = (char *)addr;
  1560.             }
  1561.         if (envcnt)
  1562.             {
  1563.             umemset(crp, (long)--addr, 0, sizeof(long));
  1564.             for (i = envcnt; i--; )
  1565.                 ukmemcpy(crp, (long)--addr, &envs[i], sizeof(long));
  1566.             ukmemcpy(crp, (long)(addr-1), &addr, sizeof(long));
  1567.             addr--;
  1568.             }
  1569.         umemset(crp, (long)--addr, 0, sizeof(long));
  1570.         for (i = argcnt; i--; )
  1571.             ukmemcpy(crp, (long)--addr, &args[i], sizeof(long));
  1572.         ukmemcpy(crp, (long)--addr, args, sizeof(long));
  1573.         crp->registers.save[15] = (long)addr;
  1574.         crp->registers.save[14] = argcnt;
  1575.         free(envs);
  1576.         free(args);
  1577. #endif
  1578.         }
  1579.     else
  1580.         crp->registers.save[15] = stack_limit-256;
  1581.     if (kbuf)
  1582.         {
  1583.         int proc = open(kbuf, O_RDONLY);
  1584.         if (proc < 0)
  1585.             {
  1586.             crp->state = 'Z';
  1587.             return proc;
  1588.             }
  1589.         if (parent)
  1590.             {
  1591.             memcpy(crp->fd_tab, parent->fd_tab, sizeof(crp->fd_tab));
  1592.             crp->trace_me = parent->trace_me;
  1593.             }
  1594.         else
  1595.             crp->fd_tab[0] = crp->fd_tab[1] = crp->fd_tab[2] = 1;
  1596.         read(proc, (void *)&(crp->header), sizeof(crp->header));
  1597.         if (N_BADMAG(crp->header))
  1598.             {
  1599.             char **args;
  1600.             long *addr = (long *)(crp->registers.save[15]);
  1601.             char *default_shell = "/bin/sh";
  1602.             char *shell = (char *)&(crp->header);
  1603.             if (*shell++ != '#') shell = default_shell;
  1604.             else if (*shell++ == '!')
  1605.                 {
  1606.                 char *end = strchr(shell,'\n');
  1607.                 if (end) *end = 0;
  1608.                 else shell = default_shell;
  1609.                 }
  1610.             else shell = default_shell;
  1611.             close(proc);
  1612.             proc = open(shell, O_RDONLY);            
  1613.             read(proc, (void *)&(crp->header), sizeof(crp->header));
  1614.             if (N_BADMAG(crp->header))
  1615.                 {
  1616.                 errno = ENOEXEC;
  1617.                 crp->state = 'Z';
  1618.                 return -1;
  1619.                 }
  1620.             kumemcpy(crp, args, (long)addr, sizeof(long));
  1621.             ukmemcpy(crp, (long)--addr, args, sizeof(long));
  1622.             crp->registers.save[15] = (long)addr;
  1623.             crp->registers.save[14]++;
  1624.             
  1625.             }
  1626.         crp->sbreak = N_ALIGN(crp->header, N_BSSADDR(crp->header) + crp->header.a_bss);
  1627.         if (lower_space(crp, crp->sbreak))
  1628.             {
  1629.             crp->state = 'Z';
  1630.             return -1;
  1631.             }
  1632.         lseek(proc, N_TXTOFF(crp->header), 0);
  1633.         uread(crp,proc, N_TXTADDR(crp->header), crp->header.a_text);
  1634.         if (0) lseek(proc, N_DATOFF(crp->header), 0);
  1635.         uread(crp,proc,N_DATADDR(crp->header), crp->header.a_data);
  1636.         close(proc);
  1637.         umemset(crp,N_BSSADDR(crp->header), 0, crp->header.a_bss);
  1638.         if (parent) parent->state = 'Z';
  1639.         crp->registers.pc = crp->header.a_entry;
  1640.         }
  1641.     else
  1642.         {
  1643.         int usp = parent->registers.save[15];
  1644.         crp->sbreak = parent->sbreak;
  1645.         crp->registers = parent->registers;
  1646.         if (lower_space(crp, crp->sbreak))
  1647.             {
  1648.             crp->state = 'Z';
  1649.             return -1;
  1650.             }
  1651.         uumemcpy(crp, parent, 0, 0, crp->sbreak);    /* duplicate prog+data space */
  1652.         if (upper_space(crp, stack_limit-usp+stack_headroom))
  1653.             {
  1654.             crp->state = 'Z';
  1655.             return -1;
  1656.             }
  1657.         uumemcpy(crp, parent, usp, usp, stack_limit-usp);    /* duplicate stack space */
  1658.         memcpy(crp->fd_tab, parent->fd_tab, sizeof(crp->fd_tab));
  1659.         crp->header = parent->header;
  1660.         crp->root_parID = parent->root_parID;
  1661.         crp->crt_parID = parent->crt_parID;
  1662.         crp->trace_me = parent->trace_me;
  1663.         }
  1664.     return 0;
  1665.     }
  1666.  
  1667. /* Prototypes */
  1668. OSErr InstallVBL (void);
  1669. pascal long GetVBLRec (void);
  1670. void DoVBL (unsigned short fault);
  1671.     
  1672. _main(int argc, char **argv)
  1673.     {
  1674.     long *addr;
  1675.     int proc;
  1676.     page_size = tc()&16384?8192:4096;
  1677.     for (ccnt = 8; ccnt--; ) nxt[ccnt] = GetCursor(128+ccnt);
  1678.     
  1679.     patch_traps();
  1680.     InstallVBL();
  1681.  
  1682.     root_parID = crt_parID;
  1683.     crp = 0;
  1684.     if (newproc(argv[1], 0, 0, 0)) 
  1685.         {
  1686.         kInterval = 0;
  1687.         exit(-2);
  1688.         }
  1689.     asm    { trap #0 };
  1690.     }
  1691.  
  1692. typedef struct VBLRec {
  1693.     VBLTask    myVBLTask;
  1694.     long    vblA5;    /* 4 bytes before the VBLTask data */
  1695. } VBLRec, *VBLRecPtr;
  1696.  
  1697. /* Globals */
  1698. VBLRec gMyVBLRec;    /* global VBL record */
  1699.  
  1700. pascal long GetVBLRec (void)
  1701.     = 0x2E88;
  1702.  
  1703. OSErr InstallVBL ()
  1704. {
  1705.     long addr,addr2;
  1706.     long page = page_alloc();
  1707.     char *buf = (void *)xmalloc(512+sizeof(struct mmu));
  1708.     swapper = (struct mmu *)((((long)buf)|511)+1);
  1709.     swapper->self = buf;
  1710.     memset((void *)page, 0x4E, page_size);
  1711.     for (addr = 0; addr < 128; addr++)
  1712.         {
  1713.         swapper->level1[addr] = 0xA + (long)(swapper->level2);
  1714.         swapper->level2[addr] = 0xA + (long)&(swapper->level3[addr][0]);
  1715.         for (addr2 = (1<<18)/page_size; addr2--; )
  1716.             {
  1717.             swapper->level3[addr][addr2] = 0x39 + page;
  1718.             }
  1719.         }
  1720.     gMyVBLRec.myVBLTask.qType = vType;
  1721.     gMyVBLRec.myVBLTask.vblAddr = (ProcPtr) DoVBL;/* address of task */
  1722.     gMyVBLRec.myVBLTask.vblCount = kInterval; /* Set the interval */
  1723.     gMyVBLRec.vblA5 = (long) CurrentA5; /* Save app's A5 in structure */
  1724.  
  1725.     return VInstall((QElemPtr) &gMyVBLRec.myVBLTask);
  1726. }
  1727.  
  1728. /* ============= the VBL task code itself  =============*/
  1729.  
  1730. void DoVBL(unsigned short fault)
  1731.     {
  1732.     long    curA5;
  1733.     VBLRecPtr    recPtr;
  1734.  
  1735.     recPtr = (VBLRecPtr) GetVBLRec ();
  1736.     curA5 = SetA5 (recPtr->vblA5);
  1737.                                     /* read app A5 from structure and save */
  1738.                                         /* current value of A5 */
  1739.  
  1740.     /* ...  now that it's OK to access application variables, do the task ... */
  1741.  
  1742.     pflusha();
  1743.     pflushan();
  1744.     if (vbr()) put_urp((long)swapper);
  1745.     pflusha();
  1746.     pflushan();
  1747.  
  1748.     /* Reset vblCount so that this procedure executes again */
  1749.     recPtr->myVBLTask.vblCount = kInterval;
  1750.     curA5 = SetA5(curA5);
  1751.     }
  1752.